﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Management;

namespace System.Peppers.Wmi
{
    /// <summary>
    /// The Win32_UserAccount WMI class contains information about a user account on a computer system running Windows.
    /// </summary>
    public sealed class UserAccount : Account
    {
        #region Static
        private static class WmiProperties
        {
            public const string AccountType = "AccountType",
                Disabled = "Disabled",
                Domain = "Domain",
                FullName = "FullName",
                Lockout = "Lockout",
                Name = "Name",
                PasswordChangeable = "PasswordChangeable",
                PasswordExpires = "PasswordExpires",
                PasswordRequired = "PasswordRequired";
        }

        private static class WmiMethods
        {
            public const string Rename = "Rename";
        }

        private static class WmiParameters
        {
            public const string Name = "Name";
        }

        /// <summary>
        /// Enumerates user accounts on the system.  Because both the Name and Domain are key properties, enumerating Win32_UserAccount on a large network can negatively affect performance.  I will add better methods in the future.
        /// </summary>
        /// <returns>List of user accounts</returns>
        public static IEnumerable<UserAccount> GetAccounts()
        {
            foreach (ManagementObject item in GetInstances(WmiClasses.Win32_UserAccount))
            {
                yield return new UserAccount(item);
            }
        }

        /// <summary>
        /// Enumerates user accounts on a remote system.  Because both the Name and Domain are key properties, enumerating Win32_UserAccount on a large network can negatively affect performance.  I will add better methods in the future.
        /// </summary>
        /// <param name="remoteParams">Connection options for remote system</param>
        /// <returns>List of user accounts</returns>
        public static IEnumerable<UserAccount> GetAccounts(WmiRemoteParameters remoteParams)
        {
            foreach (ManagementObject item in GetInstances(WmiClasses.Win32_UserAccount, remoteParams))
            {
                yield return new UserAccount(item);
            }
        }
        #endregion

        internal UserAccount(ManagementObject wmiObject)
            : base(wmiObject)
        { }

        /// <summary>
        /// Flags that describe the characteristics of a Windows user account.
        /// </summary>
        public UserAccountType AccountType
        {
            get { return (UserAccountType)Convert.ToUInt32(this[WmiProperties.AccountType] ?? 0); }
        }

        /// <summary>
        /// Windows user account is disabled.
        /// </summary>
        public bool Disabled
        {
            get { return Convert.ToBoolean(this[WmiProperties.Disabled] ?? false); }
            set { this[WmiProperties.Disabled] = value; }
        }

        /// <summary>
        /// Name of the Windows domain to which a user account belongs, for example: "NA-SALES".
        /// </summary>
        public string Domain
        {
            get { return Convert.ToString(this[WmiProperties.Domain]); }
        }

        /// <summary>
        /// Full name of a local user, for example: "Dan Wilson".
        /// </summary>
        public string FullName
        {
            get { return Convert.ToString(this[WmiProperties.FullName]); }
            set { this[WmiProperties.FullName] = value; }
        }

        /// <summary>
        /// If True, the user account is locked out of the Windows operating system.
        /// </summary>
        public bool Lockout
        {
            get { return Convert.ToBoolean(this[WmiProperties.Lockout] ?? false); }
            set { this[WmiProperties.Lockout] = value; }
        }

        /// <summary>
        /// Name of the Windows user account on the domain that the Domain property of this class specifies.
        /// </summary>
        public string Name
        {
            get { return Convert.ToString(this[WmiProperties.Name]); }
        }

        /// <summary>
        /// If True, the password on this user account can be changed
        /// </summary>
        public bool PasswordChangeable
        {
            get { return Convert.ToBoolean(this[WmiProperties.PasswordChangeable] ?? false); }
            set { this[WmiProperties.PasswordChangeable] = value; }
        }

        /// <summary>
        /// If True, the password on this user account expires.
        /// </summary>
        public bool PasswordExpires
        {
            get { return Convert.ToBoolean(this[WmiProperties.PasswordExpires] ?? false); }
            set { this[WmiProperties.PasswordExpires] = value; }
        }

        /// <summary>
        /// If True, a password is required on a Windows user account. If False, this account does not require a password.
        /// </summary>
        public bool PasswordRequired
        {
            get { return Convert.ToBoolean(this[WmiProperties.PasswordRequired] ?? false); }
            set { this[WmiProperties.PasswordRequired] = value; }
        }
        
        /// <summary>
        /// The Rename WMI class method renames a user account name. This functionality is implemented as a method to provide a separate context for the new name that is distinguishable from the key property value for Name that is associated with the instance to be modified.
        /// </summary>
        /// <param name="name">New account name.</param>
        /// <returns>Result of Rename() operation</returns>
        public AccountRenameResult Rename(string name)
        {
            return (AccountRenameResult)ExecuteMethodWithResult(WmiMethods.Rename, delegate(ManagementBaseObject inParam)
            {
                inParam[WmiParameters.Name] = name;
            });
        }
    }
}
